package cn.schoolwow.flow.monitor.module.business.scheduleJob.initial.flow;

import cn.schoolwow.flow.monitor.domain.FlowMonitorOption;
import cn.schoolwow.flow.monitor.entity.ScheduleJob;
import cn.schoolwow.flow.monitor.module.business.scheduleJob.definition.domain.ScheduleJobContext;
import cn.schoolwow.flow.monitor.module.business.scheduleJob.definition.flow.business.GetScheduleJobContextListFlow;
import cn.schoolwow.quickdao.domain.database.dml.CompareInstanceListResult;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.beanCopy.BeanCopy;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;

import java.util.List;
import java.util.concurrent.ScheduledFuture;

public class InitialScheduleJobFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        insertScheduleJob(flowContext);
        startScheduleJob(flowContext);
    }

    @Override
    public String name() {
        return "初始化定时任务";
    }

    private void insertScheduleJob(FlowContext flowContext){
        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);

        FlowMonitorOption flowMonitorOption = applicationContext.getBean(FlowMonitorOption.class);

        flowContext.executeFlowList(new GetScheduleJobContextListFlow());
        List<ScheduleJobContext> scheduleJobContextList = flowContext.getData("list", List.class);
        if(null==scheduleJobContextList||scheduleJobContextList.isEmpty()){
            flowMonitorOption.dao.clear(ScheduleJob.class);
            flowContext.brokenCurrentFlow("定时任务列表为空");
        }
        List<ScheduleJob> scheduleJobList = BeanCopy.cloneObjectList(scheduleJobContextList,ScheduleJob.class);
        for(ScheduleJob scheduleJob:scheduleJobList){
            scheduleJob.setEnable(true);
        }
        List<ScheduleJob> totalList = flowMonitorOption.dao.query(ScheduleJob.class).execute().getList();

        CompareInstanceListResult<ScheduleJob> compareInstanceListResult = flowMonitorOption.dao.compareInstanceList(scheduleJobList, totalList);
        flowMonitorOption.dao.insert(compareInstanceListResult.insertInstanceList);
        flowMonitorOption.dao.partColumn("cron").update(compareInstanceListResult.updateInstanceList);
        flowMonitorOption.dao.delete(compareInstanceListResult.deleteInstanceList);
    }

    private void startScheduleJob(FlowContext flowContext){
        List<ScheduleJobContext> scheduleJobContextList = flowContext.getData("list", List.class);
        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);
        ThreadPoolTaskScheduler threadPoolTaskScheduler = applicationContext.getBean(ThreadPoolTaskScheduler.class);
        FlowMonitorOption flowMonitorOption = applicationContext.getBean(FlowMonitorOption.class);

        List<ScheduleJob> scheduleJobList = flowMonitorOption.dao.query(ScheduleJob.class).execute().getList();

        for(ScheduleJobContext scheduleJobContext:scheduleJobContextList){
            ScheduleJob scheduleJob = QueryInstanceList.newQuery(scheduleJobList)
                    .addQuery("categoryName", scheduleJobContext.categoryName)
                    .addQuery("name", scheduleJobContext.name)
                    .execute()
                    .checkOne();
            if(!scheduleJob.isEnable()){
                continue;
            }
            ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(new Runnable() {
                @Override
                public void run() {
                    flowMonitorOption.scheduleQuickFlow.startFlow(scheduleJobContext.scheduleJobFlow).execute();
                }
            }, new CronTrigger(scheduleJobContext.cron));
            scheduleJobContext.scheduledFuture = scheduledFuture;
        }
    }
}
